
 ; Some arm fp macros for use in assembler.
 ; Various caveats and limitations apply.
 ; *NOT* APCS complient.

 ; "It's not very nice, but it's quick." - <mech@toth.org.uk>

 GBLA vr0
 GBLA vr1
 GBLA vr2
 GBLA vr3
 GBLA vr4
 GBLA vr5
 GBLA vr6
 GBLA vr7
 GBLA vr8
 GBLA vr9
 GBLA vr10
 GBLA vr11
 GBLA vr12
 GBLA vr13
 GBLA vr14

 GBLA vf0
 GBLA vf1
 GBLA vf2
 GBLA vf3
 GBLA vf4
 GBLA vf5
 GBLA vf6
 GBLA vf7
 GBLA vf8
 GBLA vf9
 GBLA vf10
 GBLA vf11
 GBLA vf12
 GBLA vf13
 GBLA vf14
 GBLA vf15
 GBLA vf16
 GBLA vf17
 GBLA vf18
 GBLA vf19
 GBLA vf20
 GBLA vf21
 GBLA vf22
 GBLA vf23
 GBLA vf24
 GBLA vf25
 GBLA vf26
 GBLA vf27
 GBLA vf28
 GBLA vf29
 GBLA vf30
 GBLA vf31
 GBLA vf32
 GBLA vf33
 GBLA vf34
 GBLA vf35
 GBLA vf36
 GBLA vf37
 GBLA vf38
 GBLA vf39
 GBLA vf40
 GBLA vf41
 GBLA vf42
 GBLA vf43
 GBLA vf44

vr0  SETA 0
vr1  SETA 4
vr2  SETA vr1*2
vr3  SETA vr1*3
vr4  SETA vr1*4
vr5  SETA vr1*5
vr6  SETA vr1*6
vr7  SETA vr1*7
vr8  SETA vr1*8
vr9  SETA vr1*9
vr10 SETA vr1*10
vr11 SETA vr1*11
vr12 SETA vr1*12
vr13 SETA vr1*13
vr14 SETA vr1*14

vf0  SETA 0
vf1  SETA 12
vf2  SETA vf1*2
vf3  SETA vf1*3
vf4  SETA vf1*4
vf5  SETA vf1*5
vf6  SETA vf1*6
vf7  SETA vf1*7
vf8  SETA vf1*8
vf9  SETA vf1*9
vf10 SETA vf1*10
vf11 SETA vf1*11
vf12 SETA vf1*12
vf13 SETA vf1*13
vf14 SETA vf1*14
vf15 SETA vf1*15
vf16 SETA vf1*16
vf17 SETA vf1*17
vf18 SETA vf1*18
vf19 SETA vf1*19
vf20 SETA vf1*20
vf21 SETA vf1*21
vf22 SETA vf1*22
vf23 SETA vf1*23
vf24 SETA vf1*24
vf25 SETA vf1*25
vf26 SETA vf1*26
vf27 SETA vf1*27
vf28 SETA vf1*28
vf29 SETA vf1*29
vf30 SETA vf1*30
vf31 SETA vf1*31
vf32 SETA vf1*32
vf33 SETA vf1*33
vf34 SETA vf1*34
vf35 SETA vf1*35
vf36 SETA vf1*36
vf37 SETA vf1*37
vf38 SETA vf1*38
vf39 SETA vf1*39
vf40 SETA vf1*40
vf41 SETA vf1*41
vf42 SETA vf1*42
vf43 SETA vf1*43
vf44 SETA vf1*44

                             ; Macros: Caller must save at least {r0 - r9, r14}
                             ; and point r9 to area for fp registers...
 MACRO
$label _fget $reglist, $freg
 [ "$freg" != ""
  [ "$freg" = "im0"
   ASSERT "$reglist" = "{r3 - r5}"
   mov r3, #0
   mov r4, #0
   mov r5, #0
  |
   [ "$freg" = "im1"
    ASSERT "$reglist" = "{r3 - r5}"
    mov r3, #0x4000
    sub r3, r3, #1
    mov r4, #1<<31
    mov r5, #0
   |
    [ "$freg" = "f0"
     ldmia r9, $reglist
    |
     add r7, r9, #v$freg
     ldmia r7, $reglist
    ]
   ]
  ]
 ]
 MEND

 MACRO
$label _fsave $freg, $reglist
 [ "$freg" != ""
  [ "$freg" = "f0"
   stmia r9, $reglist
  |
   add r7, r9, #v$freg
   stmia r7, $reglist
  ]
 ]
 MEND

 MACRO
$label _mvf $fdest, $fsrc
 _fget {r0 - r2}, $fsrc
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _mvf2 $fdest, $fsrc
 _fget {r3 - r5}, $fsrc
 _fsave $fdest, {r3 - r5}
 MEND

 MACRO
$label _ldfs $freg, $reg, $off
 [ "$reg" = ""
  ldr r0, [$off]
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   ldr r0, [$reg, $off]
  |
   ldr r0, [r13, #v$reg]
   ldr r0, [r0, $off]
  ]
 ]
 bl |mech_ldfs|
 _fsave $freg, {r0 - r2}
 MEND

 MACRO
$label _ldfs2 $freg, $reg, $off
 [ "$reg" = ""
  ldr r3, [$off]
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   ldr r3, [$reg, $off]
  |
   ldr r3, [r13, #v$reg]
   ldr r3, [r3, $off]
  ]
 ]
 bl |mech_ldfs_op2|
 _fsave $freg, {r3 - r5}
 MEND

 MACRO
$label _ldfd $freg, $reg, $off
 [ "$reg" = ""
  ldmia $off, {r0, r2}
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   [ "$off" != "#0"
    add r0, $reg, $off
    ldmia r0, {r0, r2}
   |
    ldmia $reg, {r0, r2}
   ]
  |
   ldr r0, [r13, #v$reg]
   [ "$off" != "#0"
    add r0, r0, $off
   ]
   ldmia r0, {r0, r2}
  ]
 ]
 bl |mech_ldfd|
 _fsave $freg, {r0 - r2}
 MEND

 MACRO
$label _ldfd2 $freg, $reg, $off
 [ "$reg" = ""
  ldmia $off, {r3, r5}
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   [ "$off" != "#0"
    add r3, $reg, $off
    ldmia r3, {r3, r5}
   |
    ldmia $reg, {r3, r5}
   ]
  |
   ldr r3, [r13, #v$reg]
   [ "$off" != "#0"
    add r3, r3, $off
   ]
   ldmia r3, {r3, r5}
  ]
 ]
 bl |mech_ldfd_op2|
 _fsave $freg, {r3 - r5}
 MEND

 MACRO
$label _stfs $freg, $reg, $off
 _fget {r0 - r2}, $freg
 bl |mech_ep_to_sng|
 [ "$reg" = ""
  str r0, [$off]
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   str r0, [$reg, $off]
  |
   ldr r7, [r13, #v$reg]
   str r0, [r7, $off]
  ]
 ]
 MEND

 MACRO
$label _stfs2 $freg, $reg, $off
 _fget {r3 - r5}, $freg
 bl |mech_ep_to_sng2|
 [ "$reg" = ""
  str r0, [$off]
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   str r0, [$reg, $off]
  |
   ldr r7, [r13, #v$reg]
   str r0, [r7, $off]
  ]
 ]
 MEND

 MACRO
$label _stfd $freg, $reg, $off
 _fget {r0 - r2}, $freg
 bl |mech_ep_to_doub|
 [ "$reg" = ""
  stmia $off, {r0, r1}
 |
  [ "$reg" = "r10" :LOR: "$reg" = "r11" :LOR: "$reg" = "r12"
   [ "$off" != "#0"
    add r7, $reg, $off
    stmia r7, {r0, r1}
   |
    stmia $reg, {r0, r1}
   ]
  |
   ldr r7, [r13, #v$reg]
   [ "$off" != "#0"
    add r7, r7, $off
   ]
   stmia r7, {r0, r1}
  ]
 ]
 MEND

 MACRO
$label _adfs $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_adfs|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _adfd $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_adfd|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _sufs $fdest, $fsrc1, $fsrc2
 _fget {r0-r2}, $fsrc1
 _fget {r3-r5}, $fsrc2
 bl |mech_sufs|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _sufd $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_sufd|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _rsfs $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 eor r0, r0, #1<<31
 bl |mech_adfs|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _rsfd $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 eor r0, r0, #1<<31
 bl |mech_adfd|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _cass $fdest1, $fdest2, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_cass|
 _fsave $fdest1, {r0 - r2}  ; subtracted
 _fsave $fdest2, {r3 - r5}  ; added
 MEND

 MACRO
$label _rcss $fdest1, $fdest2, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_cass|
 eor r0, r0, #1<<31
 _fsave $fdest1, {r0 - r2}  ; reverse subtracted
 _fsave $fdest2, {r3 - r5}  ; added
 MEND

 MACRO
$label _fmls $fdest, $fsrc1, $fsrc2
 _fget {r0-r2}, $fsrc1
 _fget {r3-r5}, $fsrc2
 bl |mech_mufs|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _mufd $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_mufd|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _fdvs $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_fdvs|
 orr r0, r0, r3
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _frds $fdest, $fsrc1, $fsrc2
 _fget {r0 - r2}, $fsrc1
 _fget {r3 - r5}, $fsrc2
 bl |mech_frds|
 orr r0, r0, r3
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _sqts $fdest, $fsrc
 _fget {r0 - r2}, $fsrc
 bl |mech_sqts|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _sqtd $fdest, $fsrc
 _fget {r0 - r2}, $fsrc
 bl |mech_sqtd|
 _fsave $fdest, {r0 - r2}
 MEND

 MACRO
$label _cmf $freg1, $freg2
 _fget {r0 - r2}, $freg1
 _fget {r3 - r5}, $freg2
 bl do_cmf
 msr cpsr_flg, r6
 MEND

 END
